/*
 * Created by: vadikv
 * Created: Thursday, March 06, 2008
 */

using System.Collections.Generic;
using System.Collections.ObjectModel;
using OneDayModel.Interfaces;

namespace OneDayModel.Model
{
    public class Roles : ReadOnlyCollection<IRole>
    {
        private Dictionary<string, int> rolesDictionary;
        private List<string> publicRoles;

        public Roles(IList<IRole> roles):base(roles)
        {
            BuildDictionary();
        }

        public AttributesBuilder NewAttributesBuilder()
        {
            { return new AttributesBuilder(this); }
        }

        private void BuildDictionary()
        {
            publicRoles = new List<string>();
            rolesDictionary = new Dictionary<string, int>(Count);
            for(int i = 0; i < Count; i++)
            {
                IRole role = Items[i];
                rolesDictionary.Add(role.Name, i);
                if (role.Public)
                    publicRoles.Add(role.Name);
            }
        }

        public IRole this[string roleName]
        {
            get
            {
                if (rolesDictionary.ContainsKey(roleName))
                    return Items[rolesDictionary[roleName]];
                else
                    return null;
            }
        }

        public string[] ToStringArray()
        {
            return publicRoles.ToArray();
        }

        

    }

    public class AttributesBuilder : IAttributesBuilder
    {
        private readonly Roles roles;
        private readonly SortedList<string, object> appendedRoles = new SortedList<string, object>();
        readonly List<IRoleAttribute> attributes = new List<IRoleAttribute>();

        internal AttributesBuilder(Roles roles)
        {
            this.roles = roles;
        }

        public IRoleAttribute[] Attributes
        {
            get { return attributes.ToArray(); }
        }

        public void AppendRole(string roleName)
        {
            AppendRole(roleName, attributes.Count);
        }

        private void AppendRole(string roleName, int position)
        {
            if (!appendedRoles.ContainsKey(roleName))
            {
                IRole role = roles[roleName];
                if (role != null)
                {
                    if (attributes.Count == 0)
                        attributes.AddRange(role.Attributes);
                    else
                        attributes.InsertRange(position, role.Attributes);
                    appendedRoles.Add(roleName, null);
                    AppendRole(role.Parent, 0);
                }
            }
        }
    }


    
   /* public class PublicRolesEnumerable : IEnumerable<IRole>
    {
        private readonly IEnumerable<IRole> roles;

        public PublicRolesEnumerable(IEnumerable<IRole> roles)
        {
            this.roles = roles;
        }

        IEnumerator<IRole> IEnumerable<IRole>.GetEnumerator()
        {
            return new PublicRolesEnumerator(roles.GetEnumerator());
        }

        public IEnumerator GetEnumerator()
        {
            return ((IEnumerable<IRole>)this).GetEnumerator();
        }
    }

    public class PublicRolesEnumerator : IEnumerator<IRole>
    {
        private readonly IEnumerator<IRole> enumerator;

        public PublicRolesEnumerator(IEnumerator<IRole> enumerator)
        {
            this.enumerator = enumerator;
        }

        IRole IEnumerator<IRole>.Current
        {
            get { return new Role(enumerator.Current); }
        }

        public void Dispose()
        {
            enumerator.Dispose();
        }

        public bool MoveNext()
        {
            while (enumerator.MoveNext())
            {
                if (enumerator.Current.Public)
                    return true;
            }
            return false;
        }

        public void Reset()
        {
            enumerator.Reset();
        }

        public object Current
        {
            get { return enumerator.Current; }
        }
    }

    internal class Role : IRole
    {
        private readonly string name;

        public Role(IRole rawRole)
        {
            name = rawRole.Name;
        }

        public string Name
        {
            get { return name; }
        }
    }*/
}